package com.seehack.sample.spring.extension.feign;

import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Set;

public class FeignInvokerBeanRegistrar implements ImportBeanDefinitionRegistrar {

    private String[] basePackages;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(annotationMetadata.getAnnotationAttributes(FeignInvokerScan.class.getName()));
        this.basePackages = attributes.getStringArray("basePackages");
        FeignInvokerBeanDefinitionScanner scanner = new FeignInvokerBeanDefinitionScanner(beanDefinitionRegistry);
        scanner.addIncludeFilter(new AnnotationTypeFilter(FeignInvoker.class));
        Set<BeanDefinitionHolder> beanDefinitionHolders = scanner.doScan(basePackages);
        registerBeanDefinitionHolders(beanDefinitionHolders);
    }

    private void registerBeanDefinitionHolders(Set<BeanDefinitionHolder> beanDefinitionHolders) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
            /*
             * FeignInvoker扫描到的接口转换为FeignClientFactoryBean
             * 1、设置容器创建对象为FeignClientFactoryBean
             */
            definition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();
            definition.getPropertyValues().add("type",definition.getBeanClassName());
            definition.setBeanClass(FeignClientFactoryBean.class);
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        }
    }
}
